/* gpllup.p - Low level code update -- in_mstr.in_level                 */
/* Copyright 1986-2001 QAD Inc., Carpinteria, CA, USA.                        */
/* All rights reserved worldwide.  This is an unpublished work.         */
/*V8:ConvertMode=Maintenance                                            */
/*J23R*/ /*V8:RunMode=Character,Windows                                 */
/* REVISION: 7.3     LAST EDIT: 06/14/96      BY: *G1XP* evan bishop    */
/* REVISION: 8.6      LAST MODIFIED: 03/03/98   BY: *J23R* Sandesh Mahagaokar */
/* REVISION: 9.0      LAST MODIFIED: 04/07/00   BY: *M0LL* Kirti Desai        */
/* REVISION: 9.0      LAST MODIFIED: 08/10/00   BY: *M0R6* Rajesh Thomas      */
/* REVISION: 9.1      LAST MODIFIED: 08/23/00   BY: *N0ND* Mark Brown         */
/* REVISION: 9.1      LAST MODIFIED: 09/18/01   BY: *M1LH* Mark Christian     */
     {mfglobal.i}
/*M0LL*/ define input parameter required-only like mfc_logical no-undo.
         define shared variable execname as character.
         define variable inrecid as recid no-undo.
/*M0LL** define variable inlevel as integer no-undo.                    */
         define variable level-updated as logical no-undo.
         define variable program-level as integer initial 1 no-undo.
         define variable last_count as integer no-undo.
         define variable five_eights as integer initial 88888 no-undo.
         define variable five_nines as integer initial 99999 no-undo.
         define variable ii as integer no-undo.
/*M0LL*/ define variable last-profile as character no-undo.
/*M0LL*/ define variable this-profile as character no-undo.
/*M0LL*/ {gpllupb.i "shared"}
/*M0LL*/ /* BEGIN ADD SECTION */
         /* IDENTIFY THE ZERO LEVEL ITEMS FIRST (PURCHASED OR DISTRIBUTED   */
         /* WITH INVALID SOURCE NETWORKS OR MANUFACTURED WITH NO COMPONENTS)*/
         /* SINCE THEY ARE AT THE BOTTOM OF THE LOW-LEVEL CODE CHAIN AND    */
         /* WE ARE BUILDING FROM THE GROUND UP.                             */
         define query q-inmstr-zero for inmstr-wkfl.
         define query q-in_mstr-zero for in_mstr
            fields (in_level in_part in_site).
         open query q-inmstr-zero
         for each inmstr-wkfl no-lock
            where inmstr-level = five_eights
            and (inmstr-pmcode = "P"
            or  (inmstr-pmcode = "D" and inmstr-bom-network = ""))
         query-tuning (cache-size 100 row).
         get first q-inmstr-zero.
         repeat:
            if not available inmstr-wkfl then leave.
            do ii = 1 to 100:
               if not available inmstr-wkfl then leave.
               open query q-in_mstr-zero
               for each in_mstr no-lock
                  where in_part = inmstr-part
                  and   in_site = inmstr-site
                  and   in_level <> 0.
               get first q-in_mstr-zero exclusive-lock no-wait.
               if available in_mstr then do:
                  if locked in_mstr = no then
                     assign
                        in_level     = 0
                        inmstr-level = 0.
               end. /* IF AVAILABLE IN_MSTR */
               else inmstr-level = 0.
               if ii < 100 then get next q-inmstr-zero.
            end. /* DO II = 1 TO 100 */
            get next q-inmstr-zero.
         end. /* REPEAT */
         open query q-inmstr-zero
         for each inmstr-wkfl no-lock
            where inmstr-level = five_eights
         query-tuning (cache-size 100 row).
         get first q-inmstr-zero.
         repeat:
            if not available inmstr-wkfl then leave.
            do ii = 1  to 100:
               if not available inmstr-wkfl then leave.
               level-updated = yes.
               if inmstr-pmcode = "D" then do:
                  if can-find (first ssd_det
                     where ssd_network = inmstr-bom-network
                     and   ssd_rec_site = inmstr-site) then
                     level-updated = no.
               end. /* IF INMSTR-PMCODE = "D" */
               else if inmstr-pmcode <> "P" then do:
                  if can-find (first ps_mstr
                     where ps_par = inmstr-bom-network) then
                     level-updated = no.
               end. /* ELSE IF INMSTR-PMCODE <> "P" */
               if level-updated = yes then do:
                  open query q-in_mstr-zero
                  for each in_mstr no-lock
                     where in_part = inmstr-part
                     and   in_site = inmstr-site
                     and   in_level <> 0.
                  get first q-in_mstr-zero exclusive-lock no-wait.
                  if available in_mstr then do:
                     if locked in_mstr = no then
                        assign
                           in_level     = 0
                           inmstr-level = 0.
                  end. /* IF AVAILABLE IN_MSTR */
                  else inmstr-level = 0.
               end. /* IF LEVEL-UPDATED = YES */
               if ii < 100 then get next q-inmstr-zero.
            end. /* DO II = 1 TO 100 */
            get next q-inmstr-zero.
         end. /* REPEAT */
         close query q-inmstr-zero.
         close query q-in_mstr-zero.
/*M0LL*/ /* END ADD SECTION */
/*M0LL*/ define query q-inmstr-wkfl for inmstr-wkfl,
/*M0LL*/    in_mstr fields (in_level in_part in_site).
         main-loop:
         repeat:
            repeat:
/*J23R*        find first in_mstr
      .        no-lock use-index in_level
      .        where in_level = five_eights no-error.
 *J23R*/
/*M0LL** BEGIN DELETE SECTION
 *
 * /*J23R*/    define query q_in_mstr for in_mstr
 * /*J23R*/       fields(in_level in_mrp in_part in_site).
 * /*J23R*/    open query q_in_mstr for each in_mstr no-lock use-index in_level
 * /*J23R*/    where in_level = five_eights query-tuning(cache-size 100 row).
 * /*J23R*/    get first q_in_mstr.
 *
 *             if not available in_mstr then leave.
 *
 *             repeat ii = 1 to 100:
 *
 *                if not available in_mstr then leave.
 *
 *                inrecid = recid(in_mstr).
 *
 *M0LL** END DELETE SECTION */
/*M0LL*/       /* BEGIN ADD SECTION */
               open query q-inmstr-wkfl for each inmstr-wkfl no-lock
                  use-index inmstr-level
                  where inmstr-level = five_eights,
                  each in_mstr where in_part = inmstr-part
                     and in_site = inmstr-site
                     by in_mstr.in_level descending
               query-tuning (cache-size 100 row).
               get first q-inmstr-wkfl.
               if not available inmstr-wkfl then leave.
               repeat:
                  if not available inmstr-wkfl then leave.
                  do ii = 1 to 100:
                     if not available inmstr-wkfl then leave.
/*M0LL*/       /* END ADD SECTION */
                     level-updated = no.
/*M0LL**             do transaction:                                     */
/*J23R*              find in_mstr exclusive-lock
      .              where recid(in_mstr) = inrecid no-wait no-error.
 *J23R*/
/*M0LL** /*J23R*/    get current q_in_mstr exclusive-lock no-wait.       */
/*M0LL**             if available in_mstr and in_level = five_eights then do: */
/*M0LL*/             /* BEGIN ADD SECTION */
                     get current q-inmstr-wkfl exclusive-lock no-wait.
                     if locked in_mstr then do:
                        get next q-inmstr-wkfl.
                        next.
                     end. /* IF LOCKED IN_MSTR */
                     if available in_mstr then do:
                        inlevel = inmstr-level.
                        if inmstr-pmcode = "P" then do:
                            /* ITEM IS PURCHASED, ITS LOW-LEVEL CODE IS ZERO */
                            inlevel = 0.
                        end. /* IF INMSTR-PMCODE = "P" */
                        else if inmstr-pmcode = "D" then do:
                           /* CALCULATE LOW-LEVEL CODE FOR DRP ITEM */
                           {gprun.i ""ppllupb.p""
                           "(inmstr-part,
                             inmstr-bom-network,
                             inmstr-site,
                             input-output inlevel)" }
                        end. /* IF INMSTR-PMCODE = "D" */
                        else do:
                           /* CALCULATE LOW-LEVEL CODE FOR MANUFACTURED ITEM */
                              {gprun.i ""ppllupa.p""
                              "(inmstr-bom-network,
                                inmstr-site,
                                input-output inlevel)" }
                        end. /* ELSE DO */
/*M0LL*/                /* END ADD SECTION */
/*M0LL**                /* Calculate new low level code */                  */
/*M0LL**                {gprun.i ""ppllupc.p"" "(inrecid, output inlevel)"} */
/*M0LL**                if inlevel = five_nines then in_level = inlevel.    */
/*M0LL**                else                                                */
/*M0LL**                if inlevel < in_level then do:                      */
/*M0LL*/                if inlevel < in_level then
                           level-updated = yes.
/*M1LH** /*M0R6*/       if inlevel = ? then inmstr-level = five_nines.      */
/*M1LH** /*M0LL*/       if inlevel < five_nines then                        */

/*M1LH*/                /* UPDATE inmstr-wkfl.inmstr-level                  */
/*M1LH*/                if inlevel = ?
/*M1LH*/                or inlevel > five_eights
/*M1LH*/                then
/*M1LH*/                   inmstr-level = five_nines.
/*M1LH*/                else
/*M0LL*/                   assign
/*M0LL*/                      inmstr-level = inlevel
                              in_level     = inlevel.
/*M0LL**                end.                                                */
                     end. /* IF AVAILABLE IN_MSTR */
/*M0LL**             end. /* DO TRANSACTION */                              */
/*M0LL**             if level-updated then do:                              */
/*M0LL*/             if level-updated and
/*M0LL*/                required-only = yes then do:
                   /* Flag 'parent' items of this item/site to be processed */
/*M0LL**                {gprun.i ""ppllupd.p""                              */
/*M0LL**                "(inrecid,input-output program-level)"}             */
/*M0LL*/                {gprun.i ""ppllupd.p""
/*M0LL*/                "(inmstr-part, inmstr-site, inmstr-level,
/*M0LL*/                  input-output program-level)"}
                     end. /* IF LEVEL-UPDATED AND ... */
/*J23R*              find next in_mstr no-lock use-index in_level
      .              where in_level = five_eights no-error.
 *J23R*/
/*M0LL*/             if ii < 100 then get next q-inmstr-wkfl.
/*M0LL*/          end. /* DO II = 1 TO 100 */
/*M0LL** /*J23R*/ get next q_in_mstr.                                       */
/*M0LL*/          get next q-inmstr-wkfl.
               end. /* REPEAT */
/*M0R6** BEGIN DELETE SECTION
 * /*M0LL*/       if can-find (first inmstr-wkfl
 * /*M0LL*/          where inmstr-level = five_nines) then
 * /*M0LL*/          leave.
 *M0R6** END DELETE SECTION */
/*M0R6*/       if not can-find (first inmstr-wkfl
/*M0R6*/          where inmstr-level = five_eights) then
/*M0R6*/          leave.
            end. /* REPEAT */
        /* Count the number of items the low-level code update had to
           reset back to the unresolved value (in_mstr.in_level = 99999) */
/*M0LL** BEGIN DELETE SECTION
 *
 *          for each in_mstr
 * /*J23R*/ fields(in_level in_mrp in_part in_site)
 *          no-lock where in_level = five_nines
 * /*J23R*/ query-tuning(cache-size 100 row):
 *          accum "" (count).
 *          end.
 *
 *M0LL** END DELETE SECTION */
/*M0LL*/    /* BEGIN ADD SECTION */
            ii = 0.
            for each inmstr-wkfl no-lock where inmstr-level = five_nines:
               ii = ii + 1.
               if ii < 100 then
                  this-profile = this-profile
                                  + inmstr-part + ":" + inmstr-site + ":".
               accum "" (count).
            end. /* FOR EACH INMSTR-WKFL */
/*M0LL*/    /* END ADD SECTION */
            /* If after processing through all the 88888 items, we end up
               twice in a row with the same number of unresolved (99999)
               items, then there is probably some cyclical relationship the
               low level code update is unable to resolve and we'll exit.
               A count of zero means everything was resolved satisfactorily. */
            if count = 0
/*M0LL**       or last_count = count then leave main-loop.                   */
/*M0LL*/       then leave main-loop.
/*M0LL*/    if last_count = count and last-profile = this-profile then
/*M0LL*/       leave main-loop.
/*M0LL*/    assign
/*M0LL*/       last-profile = this-profile
/*M0LL*/       this-profile = ""
/*M0LL**       last_count   = count.                                         */
/*M0LL*/       last_count   = count
               count        = 0.
            /* Convert all in_mstr records with low-level code = 99999 to
               low_level code = 88888 and confirm that they reference valid
                components and sources of supply with valid in_mstr records */
            {gprun.i ""mrllupa.p""}
         end. /* REPEAT */
